package com.guomw.report.service.service.impl;

import com.alibaba.fastjson.JSON;
import com.guomw.report.common.config.Constant;
import com.guomw.report.common.utils.FileUtil;
import com.guomw.report.service.entity.DetectionIndex;
import com.guomw.report.service.entity.Report;
import com.guomw.report.service.entity.User;
import com.guomw.report.service.entity.UserGeneTesting;
import com.guomw.report.service.exceptions.NoUserException;
import com.guomw.report.service.exceptions.UpChainException;
import com.guomw.report.service.models.*;
import com.guomw.report.service.repository.DetectionIndexRepository;
import com.guomw.report.service.repository.ReportRepository;
import com.guomw.report.service.repository.UserGeneTestingRepository;
import com.guomw.report.service.repository.UserRepository;
import com.guomw.report.service.service.ChainReportService;
import com.guomw.report.service.service.ConfigService;
import com.guomw.report.service.service.CustomRenderer;
import com.guomw.report.service.service.upload.StaticResourceService;
import com.guomw.report.service.utils.HttpClientUtil;
import com.guomw.report.service.utils.HttpResult;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;


@Service
public class ChainReportServiceImpl implements ChainReportService {

    private String reportPrefix = "report_";
    private String userPrefix = "user_";
    private String tokenKey = "d95bbf6603ca205d64dfddaf80d5fbaf";

    @Autowired
    private ConfigService configService;

    @Autowired
    private StaticResourceService resourceService;

    @Autowired
    private UserGeneTestingRepository userGeneTestingRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ReportRepository reportRepository;

    @Autowired
    private DetectionIndexRepository detectionIndexRepository;

    /**
     * 找到指定编码的文件
     *
     * @param folder
     * @param code
     * @return
     */
    @Override
    public List<String> findFiles(String folder, String code) {
        List<String> list = new ArrayList<>();
        File d = new File(folder);
        for (File file : d.listFiles()) {
            if (file.getName().startsWith(code + ".")) list.add(file.getName());
        }
        return list;
    }

    /**
     * 生成报告
     *
     * @param code
     * @param files
     */
    @Override
    public void generateReport(String code, String files) throws Exception {
        UserGeneTesting userGeneTesting = userGeneTestingRepository.findOne(code);

        if (userGeneTesting.getStatus() == 4) {
            throw new Exception();
        }
        //获取文件
        List<Predict> predicts = new ArrayList<>();
        for (String item : files.split(",")) {
            if (!StringUtils.isEmpty(item)) {
                String data = FileUtil.read(configService.getReportFileFolder() + "/" + Constant.CHECKED + "/" + item);
                Predict predict = JSON.parseObject(data, Predict.class);
                predicts.add(predict);
            }
        }
        if (predicts.size() == 0) {
            throw new Exception();
        }

//        userGeneTestingRepository.updateStatus(code, 4);
        userGeneTesting.setStatus(4);
        userGeneTesting.setReports(JSON.toJSONString(predicts));
        userGeneTestingRepository.save(userGeneTesting);

    }

    /**
     * 获得报告列表
     *
     * @param code
     * @return
     */
    @Override
    public List<ReportList> getReportList(String code) {
        UserGeneTesting userGeneTesting = userGeneTestingRepository.findOne(code);
        List<Predict> predicts = JSON.parseArray(userGeneTesting.getReports(), Predict.class);

        List<Report> reports = reportRepository.findAll();


        List<ReportList> lists = new ArrayList<>();
        for (Predict predict : predicts) {
            ReportList reportList = new ReportList();

            for (Report report : reports) {
                if (report.getCode().equals(predict.getCategory()) && report.getVersion().equals(predict.getVersion())) {
                    reportList.setCode(predict.getCategory());
                    reportList.setTitle(report.getName());
                    reportList.setVersion(report.getVersion());
                    lists.add(reportList);
                }
            }
        }
        return lists;
    }


    @Override
    public ReportView viewReport(String reportCode, String reportVersion, String barCode) {
        List<Report> reports = reportRepository.findReport(reportCode, reportVersion);
        if (reports.size() == 0) {
            return null;
        }

        UserGeneTesting userGeneTesting = userGeneTestingRepository.findOne(barCode);
        if (userGeneTesting == null) {
            return null;
        }

        List<DetectionIndex> detectionIndices = detectionIndexRepository.findAll();

        Report report = reports.get(0);

        ReportView view = new ReportView();
        view.setTitle(report.getName());
        view.setTemplate(report.getTemplate());
        view.setUserName(userGeneTesting.getUserName());
        view.setUserGender(userGeneTesting.getUserGender().equals("F") ? "女" : "男");
        view.setUserAge(userGeneTesting.getUserAge());
        view.setNation("");
        view.setHistory("");
        view.setBarCode(barCode);
        view.setSampleType(report.getSampleType());
        view.setSampleAmount(report.getSampleAmount());
        DateTimeFormatter simpleDateFormat = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        String date = simpleDateFormat.format(userGeneTesting.getCreateTime());
        view.setDate(date);
        view.setSpecial(report.getSpecial());
        view.setTheory(report.getTheory());
        view.setOverview(report.getOverview());
        view.setReference(report.getReference());

        int normalAmount = 0;
        int abnormalAmount = 0;
        boolean isSafed = true;
        List<Detections> detectionsList = new ArrayList<>();
        List<Predict> predicts = JSON.parseArray(userGeneTesting.getReports(), Predict.class);
        for (Predict predict : predicts) {
            if (predict.getCategory().equals(reportCode) && predict.getVersion().equals(reportVersion)) {
                if (predict.getClasses().equals("1")) isSafed = false;

                Iterator<Map.Entry<String, Double>> iterator = predict.getLog2fc().entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Double> entry = iterator.next();

                    Detections detections = new Detections();
                    detections.setCode(entry.getKey());
                    detections.setDoubles(entry.getValue());

                    int isNormal = 1;
                    String expression = "无差异";
                    if (entry.getValue() > 1) {
                        expression = "差异上调";
                        isNormal = 0;
                    } else if (entry.getValue() < -1) {
                        expression = "差异下调";
                        isNormal = 0;
                    }
                    detections.setExpression(expression);
                    detections.setIsNormal(isNormal);
                    detections.setMeaning(isNormal == 1 ? "正常" : "风险增加");
                    detections.setExplain(findExplain(report.getId(), detectionIndices, entry.getKey(), isNormal == 1));
                    detectionsList.add(detections);

                    if (isNormal == 1) {
                        normalAmount += 1;
                    } else {
                        abnormalAmount += 1;
                    }
                }

            }
        }

        view.setDetections(detectionsList);
        try {
            view.setPictureUrl(resourceService.getResource(getReportPicture(detectionsList)).toString());
        } catch (Exception ex) {

        }
        view.setNormalAmount(normalAmount);
        view.setAbnormalAmount(abnormalAmount);
        view.setCheckResultTip(isSafed ? report.getCheckResultNormalTip() : report.getCheckResultAbnormalTip());
        view.setCheckResultSuggest(isSafed ? report.getCheckResultSuggest() : report.getCheckResultAbnormalSuggest());
        return view;
    }

    private String findExplain(Long reportId, List<DetectionIndex> detectionIndices, String code, boolean isNormal) {
        for (DetectionIndex detectionIndex : detectionIndices) {
            if (reportId == detectionIndex.getReportId() && detectionIndex.getCode().equals(code)) {
                return isNormal ? detectionIndex.getNormalExplain() : detectionIndex.getAbNormalExplain();
            }
        }
        return "";
    }

    @Override
    public String getReportPicture(List<Detections> detectionsList) {
        double[][] data = new double[1][detectionsList.size()];
        String[] rowKeys = {"目标物表达的差异倍数"};
        String[] columnKeys = new String[detectionsList.size()];
        int n = 0;
        for (Detections detections : detectionsList) {
            data[0][n] = detections.getDoubles();
            columnKeys[n] = detections.getCode();
            n++;
        }
        CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);
        try {
            return createBarChart(data, dataset, "", "", "", UUID.randomUUID().toString() + ".png");
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 柱状图
     *
     * @param dataset    数据集
     * @param xName      x轴的说明（如种类，时间等）
     * @param yName      y轴的说明（如速度，时间等）
     * @param chartTitle 图标题
     * @param charName   生成图片的名字
     * @return
     */
    public String createBarChart(double[][] data, CategoryDataset dataset, String xName,
                                 String yName, String chartTitle, String charName) throws IOException {
        Color goodColor = new Color(68, 114, 196);
        Color badColor = new Color(255, 0, 0);
        Color backgroundColor = new Color(255, 255, 255);
        Color fontColor = new Color(149, 149, 149);

        JFreeChart chart = ChartFactory.createBarChart(chartTitle, // 图表标题
                xName, // 目录轴的显示标签
                yName, // 数值轴的显示标签
                dataset, // 数据集
                PlotOrientation.VERTICAL, // 图表方向：水平、垂直
                false, // 是否显示图例(对于简单的柱状图必须是false)
                false, // 是否生成工具
                false // 是否生成URL链接
        );
        chart.setBorderPaint(backgroundColor);
        chart.setBorderVisible(true);
        Font labelFont = new Font("微软雅黑", Font.TRUETYPE_FONT, 12);
        /*
         * VALUE_TEXT_ANTIALIAS_OFF表示将文字的抗锯齿关闭,
         * 使用的关闭抗锯齿后，字体尽量选择12到14号的宋体字,这样文字最清晰好看
         */
        // chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
//        chart.setTextAntiAlias(false);
        chart.setBackgroundPaint(Color.white);
        // create plot
        CategoryPlot plot = chart.getCategoryPlot();
        // 设置横虚线可见
        plot.setRangeGridlinesVisible(true);
        // 虚线色彩
        plot.setRangeGridlinePaint(Color.gray);

        // 数据轴精度
//        NumberAxis vn = (NumberAxis) plot.getRangeAxis();
//        // vn.setAutoRangeIncludesZero(true);
//        DecimalFormat df = new DecimalFormat("#0.00");
//        vn.setNumberFormatOverride(df); // 数据轴数据标签的显示格式
        // x轴设置
        CategoryAxis domainAxis = plot.getDomainAxis();

        domainAxis.setLabelPaint(fontColor);
        domainAxis.setLabelFont(labelFont);// 轴标题
        domainAxis.setTickLabelFont(labelFont);// 轴数值

        // Lable（Math.PI/3.0）度倾斜
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 5.0));
//        domainAxis.setCategoryLabelPositionOffset(-150);
//        domainAxis.setMaximumCategoryLabelWidthRatio(1f);// 横轴上的 Lable 是否完整显示

        // 设置距离图片左端距离
        domainAxis.setLowerMargin(0.1);
        // 设置距离图片右端距离
        domainAxis.setUpperMargin(0.1);
        // 设置 columnKey 是否间隔显示
        // domainAxis.setSkipCategoryLabelsToFit(true);

        plot.setDomainAxis(domainAxis);
        // 设置柱图背景色（注意，系统取色的时候要使用16位的模式来查看颜色编码，这样比较准确）
        plot.setBackgroundPaint(backgroundColor);

        // y轴设置
        ValueAxis rangeAxis = plot.getRangeAxis();
        rangeAxis.setLabelFont(labelFont);
        rangeAxis.setLabelPaint(fontColor);
        rangeAxis.setTickLabelFont(labelFont);
        // 设置最高的一个 Item 与图片顶端的距离
        rangeAxis.setUpperMargin(0.15);
        // 设置最低的一个 Item 与图片底端的距离
        rangeAxis.setLowerMargin(0.15);
        plot.setRangeAxis(rangeAxis);

        CustomRenderer renderer = new CustomRenderer(data);
        // 设置柱子宽度
        renderer.setMaximumBarWidth(0.05);
        // 设置柱子高度
        renderer.setMinimumBarLength(0.2);
        // 设置柱子边框颜色
//        renderer.setBaseOutlinePaint(Color.BLACK);
        // 设置柱子边框可见
//        renderer.setDrawBarOutline(true);

        // // 设置柱的颜色
        renderer.setSeriesPaint(0, goodColor);
        if (data[0].length > 0 && Math.abs(data[0][0]) > 1) renderer.setSeriesPaint(0, badColor);
//        renderer.setSeriesPaint(1, new Color(153, 204, 255));
//        renderer.setSeriesPaint(2, new Color(51, 204, 204));

        // 设置每个地区所包含的平行柱的之间距离
        renderer.setItemMargin(0.0);

        // 显示每个柱的数值，并修改该数值的字体属性
        renderer.setIncludeBaseInRange(true);
        renderer
                .setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        renderer.setBaseItemLabelsVisible(true);

        plot.setRenderer(renderer);
        // 设置柱的透明度
        plot.setForegroundAlpha(1.0f);

//        int width = num * 80 + 60;
//        if (width > 640) width = 640;
//        int height = (int) (width * 0.6f);

        int width = 500;
        int height = 400;
        FileOutputStream fos_jpg = null;
        try {
            String chartName = configService.getReportFileFolder() + "/" + Constant.PIC + "/" + charName;
            fos_jpg = new FileOutputStream(chartName);
            ChartUtilities.writeChartAsPNG(fos_jpg, chart, width, height, true, 10);
            fos_jpg.close();

//            File file = new File(charName);
//            file.setReadable(true);

            return "/" + Constant.REPORT + "/" + Constant.PIC + "/" + charName;
        } catch (Exception e) {
            return null;
        } finally {
            if (fos_jpg != null) fos_jpg.close();
        }
    }


    /**
     * 数据上链
     *
     * @param code
     * @param files
     * @param keywords
     * @param mobile
     * @param GCode
     * @param MCode
     */
    @Override
    public void uploadChain(String code, String files, String keywords, String mobile, String GCode, String MCode) throws Exception {
        UserGeneTesting userGeneTesting = userGeneTestingRepository.findOne(code);

        String userToken = initUserToken(userGeneTesting.getUserId());
        String reportToken = initReportToken(code);


        ChainReport chainReport = new ChainReport();
        String chainData = FileUtil.read(configService.getReportFileFolder() + "/" + Constant.CHAIN + "/" + files);
        //todo remove test
//        chainData="";
        chainReport.setChainData(chainData);

        chainReport.setBarCode(userGeneTesting.getBarCode());
        chainReport.setProjectName(userGeneTesting.getProjectName());
        chainReport.setUserName(userGeneTesting.getUserName());
        chainReport.setUserGender(userGeneTesting.getUserGender());
        chainReport.setUserAge(userGeneTesting.getUserAge());
        chainReport.setUserArea(userGeneTesting.getUserArea());
        chainReport.setUserAddress(userGeneTesting.getUserAddress());
        chainReport.setUserWeight(userGeneTesting.getUserWeight());
        chainReport.setUserStature(userGeneTesting.getUserStature());

        chainReport.setUserToken(userToken);
        chainReport.setKeywords(keywords);
        chainReport.setMobile(mobile);
        chainReport.setGCode(GCode);
        chainReport.setMCode(MCode);


        HashMap<String, Object> map = new HashMap<>();
        map.put("token", reportToken);
        map.put("data", JSON.toJSONString(chainReport));
        map.put("sign", getSign(map));
        String url = configService.getChainServerUrl() + "createReport";
        HttpResult httpResult = HttpClientUtil.getInstance().post(url, map);
        if (httpResult.getHttpStatus() == HttpStatus.SC_OK) {

            Thread.sleep(10000);

            map = new HashMap<>();
            map.put("token", reportToken);
            map.put("sign", getSign(map));
            url = configService.getChainServerUrl() + "getReport";
            httpResult = HttpClientUtil.getInstance().post(url, map);
            if (httpResult.getHttpStatus() == HttpStatus.SC_OK && !StringUtils.isEmpty(httpResult.getHttpContent())) {
                userGeneTestingRepository.updateChained(code, mobile, keywords, GCode, MCode, chainData, 1);
            } else {
                throw new UpChainException();
            }
        } else {
            throw new UpChainException();
        }
    }


    /**
     * 上链前 初始化用户token及报告token
     * 上链后更新报告数据及状态
     *
     * @param code
     * @param keywords
     * @param mobile
     * @param reportUrl
     * @throws Exception
     */
//    @Override
//    public void uploadReport(String code, String keywords, String mobile, String reportUrl) throws Exception {
//        UserGeneTesting userGeneTesting = userGeneTestingRepository.findOne(code);
//
//        if (userGeneTesting.getStatus() == 4) {
//            throw new Exception();
//        }
//
//        String userToken = initUserToken(userGeneTesting.getUserId());
//        String reportToken = initReportToken(code);
//
//
//        String zipFile = configService.getResourcesHome() + "/" + reportUrl;
//
//        String destDir = configService.getResourcesHome() + "/" + StaticResourceService.REPORT_TEMP;
//        ChainReport chainReport = getReportData(zipFile, destDir);
//
//        chainReport.setBarCode(userGeneTesting.getBarCode());
//        chainReport.setProjectName(userGeneTesting.getProjectName());
//        chainReport.setUserName(userGeneTesting.getUserName());
//        chainReport.setUserGender(userGeneTesting.getUserGender());
//        chainReport.setUserAge(userGeneTesting.getUserAge());
//        chainReport.setUserArea(userGeneTesting.getUserArea());
//        chainReport.setUserAddress(userGeneTesting.getUserAddress());
//        chainReport.setUserWeight(userGeneTesting.getUserWeight());
//        chainReport.setUserStature(userGeneTesting.getUserStature());
//
//        chainReport.setUserToken(userToken);
//        chainReport.setKeywords(keywords);
//        chainReport.setMobile(mobile);
//
//
//        HashMap<String, Object> map = new HashMap<>();
//        map.put("token", reportToken);
//        map.put("data", JSON.toJSONString(chainReport));
//        map.put("sign", getSign(map));
//        String url = configService.getChainServerUrl() + "createReport";
//        HttpResult httpResult = HttpClientUtil.getInstance().post(url, map);
//        if (httpResult.getHttpStatus() == HttpStatus.SC_OK) {
//            //status
//            userGeneTestingRepository.updateReportUrl(code, mobile, keywords, reportUrl, 4);
//        } else {
//            throw new UpChainException();
//        }
//    }

    /**
     * 初始化用户token 并上链
     *
     * @param userId
     * @return
     */
    private String initUserToken(Integer userId) throws NoUserException, UnsupportedEncodingException, UpChainException {
        User user = userRepository.findOne(userId);
        if (user != null) {
            String token;
            if (StringUtils.isEmpty(user.getUserToken())) {
                token = userPrefix + DigestUtils.md5DigestAsHex((userId.toString() + tokenKey).getBytes());

                ChainUser chainUser = new ChainUser();
                chainUser.setMoney(new BigDecimal(0));
                HashMap<String, Object> map = new HashMap<>();
                map.put("token", token);
                map.put("data", JSON.toJSONString(chainUser));
                map.put("sign", getSign(map));
                String url = configService.getChainServerUrl() + "createUser";

                HttpResult httpResult = HttpClientUtil.getInstance().post(url, map);
                if (httpResult.getHttpStatus() == HttpStatus.SC_OK) {

                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                    }

                    map = new HashMap<>();
                    map.put("token", token);
                    map.put("sign", getSign(map));
                    url = configService.getChainServerUrl() + "getUser";
                    httpResult = HttpClientUtil.getInstance().post(url, map);
                    if (httpResult.getHttpStatus() == HttpStatus.SC_OK && !StringUtils.isEmpty(httpResult.getHttpContent())) {
                        userRepository.updateUserToken(userId, token);
                    } else {
                        throw new UpChainException();
                    }
                } else {
                    throw new UpChainException();
                }

            } else {
                token = user.getUserToken();
            }
            return token;
        } else {
            throw new NoUserException();
        }

    }

    /**
     * 初始化report token
     *
     * @param code
     * @return
     */
    private String initReportToken(String code) {
        String token = reportPrefix + DigestUtils.md5DigestAsHex((code + tokenKey).getBytes());
        userGeneTestingRepository.updateToken(code, token);
        return token;
    }


    /**
     * 解压文件，并获取报告数据，组装成json返回
     *
     * @param zipFile
     * @return
     */
    @Override
    public ChainReport getReportData(String zipFile, String destDir) throws Exception {

        String condition = "condition.txt";
        String result = "result";
        destDir = destDir.endsWith(File.separator) ? destDir : destDir + File.separator;

        ChainReport chainReport = new ChainReport();

        //获取文件列表
        List<String> list = unZip(zipFile, destDir, "utf-8");
        if (!list.contains(condition)) {
            return null;
        }

        String conditionData = FileUtil.read(destDir + condition);
//        chainReport.setCondition(conditionData);


        List<ChainReportItem> items = new ArrayList<>();
        for (String item : list) {
            item = item.replace("/", File.separator);
            if (item.startsWith(result + File.separator) && !item.equals(result + File.separator)) {
                String itemData = FileUtil.read(destDir + item);
                items.add(new ChainReportItem(item.replace(result + File.separator, "").replace(".count", ""), itemData));
            }
        }

//        chainReport.setResult(items);

        return chainReport;
    }


    public List<String> unZip(String zipFile, String destDir, String encoding) throws Exception {
        File zipfile = new File(zipFile);
        return unZip(zipfile, destDir, encoding);
    }


    @Override
    public List<String> unZip(String zipFile, String destDir) throws Exception {
        return unZip(zipFile, destDir, "UTF-8");
    }

    /**
     * 解压 zip 文件
     *
     * @param zipFile  zip 压缩文件
     * @param destDir  zip 压缩文件解压后保存的目录
     * @param encoding zip 文件的编码
     * @return 返回 zip 压缩文件里的文件名的 list
     * @throws Exception
     */
    public List<String> unZip(File zipFile, String destDir, String encoding) throws Exception {
        // 如果 destDir 为 null, 空字符串, 或者全是空格, 则解压到压缩文件所在目录
        if (destDir == null || destDir.length() == 0) {
            destDir = zipFile.getParent();
        }

        destDir = destDir.endsWith(File.separator) ? destDir : destDir + File.separator;
        ZipArchiveInputStream is = null;
        List<String> fileNames = new ArrayList<String>();

        try {
            is = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), 1024),
                    encoding);
            ZipArchiveEntry entry = null;

            while ((entry = is.getNextZipEntry()) != null) {
                fileNames.add(entry.getName());
                File file = new File(destDir, entry.getName());

                if (entry.isDirectory()) {
                    FileUtils.forceMkdir(file); // 创建文件夹，如果中间有路径会自动创建
                } else {
                    OutputStream os = null;

                    try {
                        FileUtils.touch(file);
                        os = new FileOutputStream(new File(destDir, entry.getName()));
                        IOUtils.copy(is, os);
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            IOUtils.closeQuietly(is);
        }

        return fileNames;
    }


    private String getSign(HashMap<String, Object> map) throws UnsupportedEncodingException {
        Map<String, String> resultMap = new TreeMap<>();
        for (Object key : map.keySet()) {
            resultMap.put(key.toString(), map.get(key.toString()).toString());
        }
        StringBuilder strB = new StringBuilder();
        resultMap.keySet().stream().filter(key -> !"sign".equals(key)).forEach(key -> strB.append(key + resultMap.get(key)));
        strB.append("4165a8d240b29af3f41818d10599d0d1");
        System.out.println(strB.toString());

        return DigestUtils.md5DigestAsHex(strB.toString().getBytes("UTF-8")).toLowerCase();
    }
}
